package com.imprenta.bean;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
import javax.faces.context.FacesContext;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.primefaces.component.submenu.Submenu;
import org.primefaces.component.menuitem.MenuItem;
import org.primefaces.model.DefaultMenuModel;
import org.primefaces.model.MenuModel;

import com.imprenta.ejb.EjbMenu;
import com.imprenta.entities.Menu;
import com.imprenta.helpers.SessionHelper;


public class MenuBean {
	
	private MenuModel model;
	/**
	 * @return the model
	 */
	public MenuModel getModel() {
		return model;
	}

	/**
	 * @param model the model to set
	 */
	public void setModel(MenuModel model) {
		this.model = model;
	}
	
	private MenuItem createMenuItem(Object o){
		
		MenuItem item = new MenuItem();
		item.setValue(((Menu)o).getNombre());
		item.setUrl(((Menu)o).getUrl());
		if (((Menu)o).getNombre().equalsIgnoreCase("Salir")) {
			FacesContext context = FacesContext.getCurrentInstance();
			ExpressionFactory factory = context.getApplication().getExpressionFactory();
			MethodExpression actionListener = factory.createMethodExpression(FacesContext.getCurrentInstance().getELContext()
				, "#{loginBean.logout()}", String.class, new Class[]{});
			item.setActionExpression(actionListener);
		}		
		return item;		
	}	
	private Submenu createSubMenu(Object o){
		
		Submenu sMenu = new Submenu();
		sMenu.setLabel(((Menu)o).getNombre());
		
		return sMenu;
	}
	@SuppressWarnings("rawtypes")
	private boolean isSubMenu(Collection<Menu> _menu, Object o){
		boolean tipo = false;
		Iterator iterator = selectByTipo(_menu, null).iterator();
		
		int id = ((Menu)o).getMenuid();
		while (iterator.hasNext()) {
			Object element = iterator.next();
			if (id == ((Menu)element).getPadre()) {
				tipo = true;
				break;
			}
			else {
				tipo = false;
			}
		}
		return tipo;
	}
	public MenuBean() {
		// TODO Auto-generated constructor stub
		if (SessionHelper.isSessionExist(LoginBean.USER_KEY)) {
			UserBean usr = SessionHelper.getUserBeanSession(LoginBean.USER_KEY);
			if (usr.getRol().equals("Cliente")) {
				createModel(usr.getRol());
			}else if (usr.getRol().equals("Vendedor")) {
				createModel(usr.getRol());
			}else if (usr.getRol().equals("Administrador")) {
				createModel();
			}
		}
		else {
			defaultModel();
		}
		//createModel("");
	}
	@SuppressWarnings("rawtypes")
	public void defaultModel(){
		model = new DefaultMenuModel();
		
		Collection<Menu> list = EjbMenu.getMenu();			
		Iterator i = selectById(list, null).iterator();
		
		while (i.hasNext()) {
			Object element = i.next();
			if (((Menu)element).getRol().equals("*")) {
				if (isSubMenu(list,element)){
					Submenu submenu = createSubMenu(element);
					addItemToSubMenu(list, element, submenu,"*");
					model.addSubmenu(submenu);
				}
				else {
					MenuItem item = createMenuItem(element);			
					model.addMenuItem(item);
				}
			}			
		}
	}
	@SuppressWarnings("rawtypes")
	public void createModel(){
		model = new DefaultMenuModel();
		
		Collection<Menu> list = EjbMenu.getMenu();			
		Iterator i = selectById(list, null).iterator();
		
		while (i.hasNext()) {
			Object element = i.next();
			
			if (isSubMenu(list,element)){
				Submenu submenu = createSubMenu(element);
				addItemToSubMenu(list, element, submenu,"Administrador");
				model.addSubmenu(submenu);
			}
			else {
				MenuItem item = createMenuItem(element);		
				model.addMenuItem(item);
			}	
		}		
	}
	@SuppressWarnings("rawtypes")
	public void createModel(String rol){
		model = new DefaultMenuModel();
		
		Collection<Menu> list = EjbMenu.getMenu();			
		Iterator i = selectById(list, null).iterator();
		
		while (i.hasNext()) {
			Object element = i.next();
			//if(sepRol(((Menu)element).getRol(), rol)){}//((Menu)element).getRol().equalsIgnoreCase(rol)
			
			if (sepRol(((Menu)element).getRol(), rol) || ((Menu)element).getRol().equals("*")) {
				if (isSubMenu(list,element)){
					Submenu submenu = createSubMenu(element);
					addItemToSubMenu(list, element, submenu, rol);
					model.addSubmenu(submenu);
				}
				else {
					MenuItem item = createMenuItem(element);			
					model.addMenuItem(item);
				}	
			}		
		}
	}
	private boolean sepRol(String roles, String rol){
		String [] aRol = roles.split(",");
		boolean existRol = false;
		for (int i = 0; i < aRol.length; i++) {
			if (rol.equalsIgnoreCase(aRol[i])) {
				existRol = true;
			}
		}
		return existRol;
	}
	@SuppressWarnings("rawtypes")
	private void addItemToSubMenu(Collection<Menu> _menu, Object o, Submenu sMenu, String rol){
		int id = ((Menu)o).getMenuid();		
		Iterator iterator = selectByTipo(_menu, null).iterator();
		
		while (iterator.hasNext()) {
			Object element = iterator.next();
			String tmp = ((Menu)element).getRol();
			
			if (id == ((Menu)element).getPadre() && (sepRol(tmp, rol) || tmp.equals("*"))) {
				MenuItem item = createMenuItem(element);
				sMenu.getChildren().add(item);
			}
		}
		
	}
	
	public Collection<Menu> selectById(Collection<Menu> cBase, final Integer catalogoid){
		Predicate predicate = new Predicate() {
			
			@Override
			public boolean evaluate(Object arg0) {
				// TODO Auto-generated method stub
				Menu _menu = (Menu) arg0;
				return _menu.getPadre() == catalogoid ? true:false;
			}
		};
		
		Collection<Menu> catalogoResult = new ArrayList<Menu>();
		CollectionUtils.select(cBase, predicate,catalogoResult);
		return catalogoResult;
	}
	
	public Collection<Menu> selectByTipo(Collection<Menu> cMenu, final Integer catalogoid){
		Predicate predicate = new Predicate() {
			
			@Override
			public boolean evaluate(Object arg0) {
				// TODO Auto-generated method stub
				Menu _menu = (Menu) arg0;				
				return _menu.getPadre() != catalogoid ? true:false;
			}
	
		};	
		
		Collection<Menu> catalogoResult = new ArrayList<Menu>();
		CollectionUtils.select(cMenu, predicate,catalogoResult);
		return catalogoResult;
	}
	

}
